package edu.cmsc611.textsimulator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;

public class ReadInput {

	private Vector<Instruction> instructions=new Vector<Instruction>();
	//private Hashtable<String,Integer> loopPCval=new Hashtable<String,Integer>();

	FunctionalUnitSingleton fu=null;

//	public void putLabel(String label, int key)
//	{
//		loopPCval.put(label, key);
//	}
//	public int getPCValueforLabel(String label)
//	{
//		if(loopPCval.get(label)!=null)
//			return loopPCval.get(label);
//		return 0;
//	}
	private Instruction tempinstr;
	public ReadInput(){};

	public Vector<Instruction> getInstructions() {
		return instructions;
	}

	public void setInstructions(Vector<Instruction> instructions) {
		this.instructions = instructions;
	}

	public void readInstructionFromFile(String instructionFile)
	{
		try {
			File file = new File(instructionFile);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			StringBuffer stringBuffer = new StringBuffer();
			String line;
			while ((line = bufferedReader.readLine()) != null)
			{
				//System.out.print(line);
				tempinstr = new Instruction(line.toUpperCase());
				//System.out.println(tempinstr);
				if (tempinstr.valid() == true)
				{
					//set size as instruction index
					tempinstr.setInstruction_index(instructions.size());
					instructions.add(tempinstr);
				}
				else
				{
					System.out.println(line+" is invalid instruction");
					return;
				}
				//stringBuffer.append(line);
				//stringBuffer.append("\n");
			}
			fileReader.close();
			//System.out.println(instructions);
			//System.out.println(stringBuffer.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void readRegisterInitialvalue(String regFile)
	{
		try {
			File file = new File(regFile);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			StringBuffer stringBuffer = new StringBuffer();
			String line;
			Registers reg=Registers.getInstance();
			int index=0;
			int regVal=0;
			while ((line = bufferedReader.readLine()) != null)
			{
				regVal=Integer.parseInt(line.trim(), 2);
				reg.setWritetoRegisterR(index, regVal);
				index++;
			}
			fileReader.close();
			//System.out.println(instructions);
			//System.out.println(stringBuffer.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void readData(String dataFile)
	{
		try {
			File file = new File(dataFile);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			StringBuffer stringBuffer = new StringBuffer();
			String line;
			DataMemory mem=DataMemory.getInstance();
			int index=256;
			int memVal=0;
			int entrynum=0;
			int blcoknum=0;
			while ((line = bufferedReader.readLine()) != null)
			{
				blcoknum=entrynum/4;

				memVal=Integer.parseInt(line.trim(), 2);
				mem.writetoDataMemory(index, memVal);
				mem.setBlock(blcoknum, index);
				entrynum++;
				index=index+4;
			}
			fileReader.close();
			//System.out.println(instructions);
			//System.out.println(stringBuffer.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void readConfigurationofSystem(String configurationfile)
	{
		fu=FunctionalUnitSingleton.getInstance();
		try {
			File file = new File(configurationfile);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			StringBuffer stringBuffer = new StringBuffer();
			String line;
			StringTokenizer tokens;
			StringTokenizer configparams;
			String unitname;
			boolean piplined=false;
			int requiredCycles=0;
			while ((line = bufferedReader.readLine()) != null)
			{
				tokens=new StringTokenizer(line,":");
				unitname=tokens.nextToken().toString().replaceAll("\\s","").toLowerCase();
				if(unitname.equals("fpadder"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					piplined=configparams.nextElement().toString().replaceAll("\\s","").toLowerCase().equals("yes")?true:false;
					//fu.setFpAdder(requiredCycles, piplined);
					fu.setIsfpAdderPiplined(piplined);
					fu.setFpAdderReqCycles(requiredCycles);

				}
				else if(unitname.equals("fpmultiplier"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					piplined=configparams.nextElement().toString().replaceAll("\\s","").toLowerCase().equals("yes")?true:false;
					//fu.setFpMultiplier(requiredCycles, piplined);
					fu.setIsfpMultiplierPiplined(piplined);
					fu.setFpMultiplierReqCycles(requiredCycles);

				}
				else if(unitname.equals("fpdivider"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					piplined=configparams.nextElement().toString().replaceAll("\\s","").toLowerCase().equals("yes")?true:false;
					//fu.setFpDivider(requiredCycles, piplined);
					fu.setIsfpDividerPiplined(piplined);
					fu.setFpDividerReqCycles(requiredCycles);

				}
				else if(unitname.equals("mainmemory"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					fu.setMainMemAccesstime(requiredCycles);
					//piplined=configparams.nextElement().toString().trim().toLowerCase().equals("yes")?true:false;

				}
				else if(unitname.equals("i-cache"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					fu.setiCacheAccessTime(requiredCycles);
					//piplined=configparams.nextElement().toString().trim().toLowerCase().equals("yes")?true:false;

				}
				else if(unitname.equals("d-cache"))
				{
					configparams=new StringTokenizer(tokens.nextToken(),",");
					requiredCycles=Integer.parseInt(configparams.nextElement().toString().replaceAll("\\s",""));
					fu.setdCacheAccesstime(requiredCycles);
					//piplined=configparams.nextElement().toString().trim().toLowerCase().equals("yes")?true:false;

				}
			}
			fileReader.close();
			//System.out.println(instructions);
			//System.out.println(stringBuffer.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		//try {
			//File file = new File("input.txt");
			ReadInput ri=new ReadInput();
			ri.readInstructionFromFile("input.txt");
			ri.readConfigurationofSystem("config.txt");
			ri.readRegisterInitialvalue("reg.txt");
			ri.readData("data.txt");
//			FileReader fileReader = new FileReader(file);
//			BufferedReader bufferedReader = new BufferedReader(fileReader);
//			StringBuffer stringBuffer = new StringBuffer();
//			String line;
//			while ((line = bufferedReader.readLine()) != null) {
//				stringBuffer.append(line);
//				stringBuffer.append("\n");
//			}
//			fileReader.close();
//			System.out.println("Contents of file:");
//			System.out.println(stringBuffer.toString());
		//} catch (IOException e) {
		//	e.printStackTrace();
		//}
	}

}

